using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using Flurl.Http;
using Pay.Core;
using Pay.Data;
using Pay.DTO;
using Pay.IService;
using Pay.Service.Cache;
using Pay.TO;

namespace Pay.Service {
    public class SettingService : ServiceBase, ISettingService, IDisposable {
        private IUnitOfWork _iUnitOfWork;

        public SettingService(IUnitOfWork iUnitOfWork) : base(iUnitOfWork) {
            _iUnitOfWork = iUnitOfWork;
        }

        public setting_dto Get() {
            return context.Settings.Where(c => c.Id == 1).FromCacheFirstOrDefault(s => {
                var setting = s.FirstOrDefault().Settings.ToObject<setting_dto>();
                return setting;
            }, "settings");
        }

        public int Save(setting_dto dto) {
            var model = context.Settings.Find(1);
            if (model == null) {
                model = new Setting();
                model.Settings = dto.ToJson();
                context.Settings.Add(model);
            } else
                model.Settings = dto.ToJson();
            int result = _iUnitOfWork.Commit("settings");
            return result;
        }

        /// <summary>
        /// 获取token设置
        /// </summary>
        /// <returns></returns>
        public token_setting_dto GetTokenSetting() {
            return context.Settings.Where(c => c.Id == 3).FromCacheFirstOrDefault(s => {
                var model = s.FirstOrDefault();
                token_setting_dto dto = model.Settings.ToObject<token_setting_dto>(); return dto;
            }, "token_settings");
        }

        /// <summary>
        /// 获取南良设置
        /// </summary>
        /// <returns></returns>
        public nl_setting_dto GetNLSetting() {
            return context.Settings.Where(c => c.Id == 5).FromCacheFirstOrDefault(s => {
                var model = s.FirstOrDefault();
                nl_setting_dto dto = model.Settings.ToObject<nl_setting_dto>(); return dto;
            }, "nl_settings");
        }

        /// <summary>
        /// 统计并更新拓垦总马力设置（定时任务调用）
        /// </summary>
        /// <returns></returns>
        public bool StatisticsTokenTotalHorsePower() {
            var log = IocHelper.Get<ILogHelper>("info");
            log.Info("拓垦统计并更新总马力---------开始");
            var total_hourse_power = context.RedRecord.Sum(o => o.TotalHorsePower);
            log.Info("当前用户总马力" + total_hourse_power);
            var snap_horse_power = context.UserSoupValueSnap.Sum(o => o.SoupValue);
            log.Info("当前用户总临时马力：" + snap_horse_power);
            token_setting_dto token_setting_dto = GetTokenSetting();
#if DEBUG
            if (total_hourse_power < 10000000)
                total_hourse_power += 10000000;
#endif
            if (token_setting_dto.token.total_horse_power < total_hourse_power) //统计总马力 大于 记录的当前用户总马力，更新
                token_setting_dto.token.total_horse_power = total_hourse_power;
            token_setting_dto.token.snap_horse_power = snap_horse_power;
            var result = Save(token_setting_dto) > 0;
            log.Info("拓垦统计并更新总马力---------结束");
            return result;
        }

        /// <summary>
        /// 保存Token设置
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public int Save(token_setting_dto dto) {
            var model = context.Settings.Where(o => o.Id == 3).FirstOrDefault();
            if (model == null) {
                model = new Setting();
                model.Settings = dto.ToJson();
                context.Settings.Add(model);
            } else
                model.Settings = dto.ToJson();
            int result = _iUnitOfWork.Commit("token_settings");
            return result;
        }

        /// <summary>
        /// 保存南良设置
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public int SaveNL(nl_setting_dto dto) {
            var model = context.Settings.Where(o => o.Id == 5).FirstOrDefault();
            if (model == null) {
                model = new Setting();
                model.Settings = dto.ToJson();
                context.Settings.Add(model);
            } else
                model.Settings = dto.ToJson();
            int result = _iUnitOfWork.Commit("nl_settings");
            return result;
        }

        public glb_setting GetGlb() {
            return context.Settings.Where(c => c.Id == 4).FromCacheFirstOrDefault(s => {
                var setting = s.FirstOrDefault().Settings.ToObject<glb_setting>();
                return setting;
            }, "glb_setting");
        }

        public int Save(glb_setting dto) {
            var model = context.Settings.Find(4);
            if (model == null) {
                model = new Setting();
                model.Settings = dto.ToJson();
                context.Settings.Add(model);
            } else
                model.Settings = dto.ToJson();
            int result = _iUnitOfWork.Commit("glb_setting");
            return result;
        }

        public void ValidCode(string mobile, string code, string use_type) {
            string key = mobile + "_" + use_type;
            if (string.IsNullOrEmpty(code))
                throw new ServerErrorException("验证码不能是空的", 1001);
            else {
                var v_code = _iUnitOfWork.GetCache<string>(key);
                if (v_code == null)
                    throw new ServerErrorException("验证码不存在", 1002);
                else {
                    if (v_code != null && v_code.ToString() != WebHelper.GetPasswrodWithTwiceEncode(code, mobile))
                        throw new ServerErrorException("验证码不正确", 1003);
                }
            }
        }
        /// <summary>
        /// 清除验证码
        /// </summary>
        /// <param name="mobile"></param>
        /// <param name="use_type"></param>
        public void RemoveCode(string mobile, string use_type) {
            string key = mobile + "_" + use_type;
            _iUnitOfWork.RomoveCache(key);
        }

        /// <summary>
        /// 发验证码
        /// </summary>
        /// <param name="send_model">发送短信请求信息</param>
        /// <returns></returns>
        public string SendRegsms(send_model send_model) {
            if (string.IsNullOrEmpty(send_model.mobile))
                throw new ServerErrorException("手机号码必须填写");
            if (string.IsNullOrEmpty(send_model.use_type))
                throw new ServerErrorException("使用类型必须");

            var setting = Get();
            var msgSetting = setting.msg.FirstOrDefault(c => c.code == send_model.use_type);
            if (msgSetting == null)
                throw new ServerErrorException("没有启用，不能发送验证码");
#if DEBUG
            _iUnitOfWork.SetCache(send_model.mobile + "_" + send_model.use_type, WebHelper.GetPasswrodWithTwiceEncode("1234", send_model.mobile), 180);
            return "0";
#else

            var v_code = DtoHelper.RandCode(send_model.code_size);
            var send_content = string.Format(msgSetting.content, v_code);
            string result = string.Empty;
            if (send_model.mobile_code == "86") {
                result = SendSms(send_model.mobile, send_content);
            } else {
                var url = string.Format("http://api2.santo.cc/submit?command=MT_REQUEST&cpid=ksxcyv&cppwd=Q5FloqaL&da={0}{1}&sm={2}",
                                        send_model.mobile_code, send_model.mobile.TrimStart('0'), send_content);
                var api_result = url.GetStringAsync().Result;
                if (api_result.Split('=').Last() == "000") result = "0";
                else result = "发送失败";
            }
            if (result == "0") {
                int times = 180;
                if (send_model.use_type == "auth") times = 600;
                _iUnitOfWork.SetCache(send_model.mobile + "_" + send_model.use_type, WebHelper.GetPasswrodWithTwiceEncode(v_code, send_model.mobile), times);
            }
            return result;
#endif
        }

        /// <summary>
        /// GLB发验证码
        /// </summary>
        /// <param name="send_model">发送短信请求信息</param>
        /// <returns></returns>
        public string SendGlbRegsms(send_model send_model) {
            if (string.IsNullOrEmpty(send_model.mobile))
                throw new ServerErrorException("手机号码必须填写");
            if (string.IsNullOrEmpty(send_model.use_type))
                throw new ServerErrorException("使用类型必须");

            var setting = GetGlb();
            var msgSetting = setting.msg.FirstOrDefault(c => c.code == send_model.use_type);
            if (msgSetting == null)
                throw new ServerErrorException("没有启用，不能发送验证码");
#if DEBUG
            _iUnitOfWork.SetCache(send_model.mobile + "_" + send_model.use_type, WebHelper.GetPasswrodWithTwiceEncode("1234", send_model.mobile), 180);
            return "0";
#else

            var v_code = DtoHelper.RandCode(send_model.code_size);
            var send_content = string.Format(msgSetting.content, v_code);
            string result = string.Empty;
            if (send_model.mobile_code == "86") {
                result = SendSms(send_model.mobile, send_content);
            } else {
                var url = string.Format("http://api2.santo.cc/submit?command=MT_REQUEST&cpid=ksxcyv&cppwd=Q5FloqaL&da={0}{1}&sm={2}",
                                        send_model.mobile_code, send_model.mobile.TrimStart('0'), send_content);
                var api_result = url.GetStringAsync().Result;
                if (api_result.Split('=').Last() == "000") result = "0";
                else result = "发送失败";
            }
            if (result == "0") {
                int times = 180;
                if (send_model.use_type == "auth") times = 600;
                _iUnitOfWork.SetCache(send_model.mobile + "_" + send_model.use_type, WebHelper.GetPasswrodWithTwiceEncode(v_code, send_model.mobile), times);
            }
            return result;
#endif
        }


        /// <summary>
        /// token 发送 验证码
        /// </summary>
        /// <param name="send_model"></param>
        /// <returns></returns>
        public string SendTokenRegsms(send_model send_model, TO.ESMSVerificationCodeSource source) {
            if (string.IsNullOrEmpty(send_model.mobile))
                throw new ServerErrorException("手机号码必须填写");
            if (string.IsNullOrEmpty(send_model.use_type))
                throw new ServerErrorException("使用类型必须");
            //if (send_model.mobile_code == "886") { throw new ServerErrorException("台湾地区暂未开放注册"); }
            if (send_model.mobile.Contains(t_RequestMethod.TestMobiePrefix)) {
                if (send_model.mobile.Length != 11) throw new ServerErrorException("手机号码不正确");
                _iUnitOfWork.SetCache(send_model.mobile + "_" + send_model.use_type, WebHelper.GetPasswrodWithTwiceEncode("1234", send_model.mobile), 180);
                return "0";
            } else {
                Regex reg = null;
                if (send_model.mobile_code == "86") {
                    reg = new Regex(@"^(13[0-9]|14[5-9]|15[012356789]|166|17[0-8]|18[0-9]|19[89])[0-9]{8}$");
                } else {
                    reg = new Regex(@"^09\d{8}$");

                }
                if (!(reg.IsMatch(send_model.mobile))) throw new ServerErrorException("手机号码不正确");
            }

            DateTime dt = DateTime.Now;
            var sms = context.SMSVerificationCode.Where(s => s.Mobile == send_model.mobile && s.CreateTime > dt.Date);
            if (sms.Count() >= 10) throw new ServerErrorException("您当天的短信已发完，请稍后再试");
#if DEBUG

            _iUnitOfWork.SetCache(send_model.mobile + "_" + send_model.use_type, WebHelper.GetPasswrodWithTwiceEncode("1234", send_model.mobile), 180);
            context.SMSVerificationCode.Add(new SMSVerificationCode { Code = "1234", CreateTime = dt, ExpirationTime = dt.AddMinutes(3), Mobile = send_model.mobile, Type = TO.ESMSVerificationCodeType.Register, Source = source });
            _iUnitOfWork.Commit();
            return "0";
#else
            var setting = GetTokenSetting().sms;
            var log = IocHelper.Get<ILogHelper>("info");
            log.Info(setting.is_open == true ? "true" : "false");
            if (!setting.is_open) {
                _iUnitOfWork.SetCache(send_model.mobile + "_" + send_model.use_type, WebHelper.GetPasswrodWithTwiceEncode("1234", send_model.mobile), 180);
                return "0";
            }
            if (send_model.mobile == "13666032381") {
                _iUnitOfWork.SetCache(send_model.mobile + "_" + send_model.use_type, WebHelper.GetPasswrodWithTwiceEncode("1234", send_model.mobile), 180);
                return "0";
            } else {
                var v_code = DtoHelper.RandCode(send_model.code_size);
                string msg_content = GetSmsContent(send_model.use_type, send_model.mobile_code);
                var send_content = string.Format(msg_content, v_code);
                string result = string.Empty;
                if (send_model.mobile_code == "86") {
                    result = SendTokenSms(send_model.mobile, send_content);
                } else {
                    var url = string.Format("http://api2.santo.cc/submit?command=MT_REQUEST&cpid=ksxcyv&cppwd=Q5FloqaL&da={0}{1}&sm={2}",
                                            send_model.mobile_code, send_model.mobile.TrimStart('0'), send_content);
                    var api_result = url.GetStringAsync().Result;
                    if (api_result.Split('=').Last() == "000") result = "0";
                    else result = "发送失败";
                }
                if (result == "0") {
                    int times = 180;
                    _iUnitOfWork.SetCache(send_model.mobile + "_" + send_model.use_type, WebHelper.GetPasswrodWithTwiceEncode(v_code, send_model.mobile), times);
                    context.SMSVerificationCode.Add(new SMSVerificationCode { Code = v_code, CreateTime = dt, ExpirationTime = dt.AddMinutes(3), Mobile = send_model.mobile, Type = TO.ESMSVerificationCodeType.Register, Source = source });
                    _iUnitOfWork.Commit();
                }
                return result;
            }


#endif
        }
        /// <summary>
        /// 通用短信验证码
        /// </summary>
        /// <param name="send_model"></param>
        /// <param name="source"></param>
        /// <returns></returns>
        public string SendCommonRegsms(send_model send_model, TO.ESMSVerificationCodeSource source,ESmsSource smsSource) {
            if (string.IsNullOrEmpty(send_model.mobile))
                throw new ServerErrorException("手机号码必须填写");
            if (string.IsNullOrEmpty(send_model.use_type))
                throw new ServerErrorException("使用类型必须");
            Regex reg = null;
            if (send_model.mobile_code == "86") {
                reg = new Regex(@"^(13[0-9]|14[5-9]|15[012356789]|166|17[0-8]|18[0-9]|19[89])[0-9]{8}$");
            } else {
                reg = new Regex(@"^09\d{8}$");
            }
            if (!(reg.IsMatch(send_model.mobile))) throw new ServerErrorException("手机号码不正确");
#if DEBUG
            _iUnitOfWork.SetCache(send_model.mobile + "_" + send_model.use_type, WebHelper.GetPasswrodWithTwiceEncode("1234", send_model.mobile), 180);
            return "0";
#else
            token_sms_setting setting = new token_sms_setting();
           List<msg_setting> msgs = new List<msg_setting>();
            if (smsSource == ESmsSource.NanLiang) {
                var nl_setting = GetNLSetting();
                setting = nl_setting.sms;
                msgs = nl_setting.msg;
            }
           
            var log = IocHelper.Get<ILogHelper>("info");
            log.Info(setting.is_open == true ? "true" : "false");
            if (!setting.is_open) {
                _iUnitOfWork.SetCache(send_model.mobile + "_" + send_model.use_type, WebHelper.GetPasswrodWithTwiceEncode("1234", send_model.mobile), 180);
                return "0";
            }
            else {
                var v_code = DtoHelper.RandCode(send_model.code_size);
                var msg= msgs.Where(s => s.code == send_model.use_type + send_model.mobile_code).FirstOrDefault();
                string msg_content = msg.content;
                var send_content = string.Format(msg_content, v_code);
                string result = string.Empty;
                DateTime dt = DateTime.Now;
                if (send_model.mobile_code == "86") {
                    result = SendCommonSms(send_model.mobile, send_content, setting);
                } else {
                    int status = SendTaiWanSms(send_model.mobile, send_content);
                    if (status == 1) result = "0";
                    else result = "发送失败";
                }
                if (result == "0") {
                    int times = 180;
                    _iUnitOfWork.SetCache(send_model.mobile + "_" + send_model.use_type, WebHelper.GetPasswrodWithTwiceEncode(v_code, send_model.mobile), times);
                    context.SMSVerificationCode.Add(new SMSVerificationCode { Code = v_code, CreateTime = dt, ExpirationTime = dt.AddMinutes(3), Mobile = send_model.mobile, Type = TO.ESMSVerificationCodeType.Register, Source = source });
                    _iUnitOfWork.Commit();
                }
                return result;
            }


#endif
        }
        /// <summary>
        /// 发短信
        /// </summary>
        /// <param name="mobile"></param>
        /// <param name="text"></param>
        /// <returns></returns>
        public string SendSms(string mobile, string text) {
#if DEBUG
            return "0";
#else
            var sms = Get().sms;
            var data = new {
                username = sms.sms_name, password = SecureHelper.MD5(sms.sms_key), to = mobile,
                text, encode = 1, msgType = 1, version = "1.0"
            };
            var result = sms.sms_url.PostJsonAsync(data).ReceiveString().Result;
            return GetSmsError(int.Parse(result));
            //PostMsg postMsg = new PostMsg();
            //var smsip = DTO.RequestMethod.sms_url.Split(':');
            ////postMsg.SetGateWay("192.168.0.208", 8088, LinkType.SHORTLINK);// 设置上行网关地址、端口
            //postMsg.SetMOAddress(smsip[0], int.Parse(smsip[1]), LinkType.SHORTLINK);// 设置下行网关地址、端口   mos:mt：211.147.239.62 端口：9080
            //return GetSmsError(postMsg.Post(postMsg.SetUser(DTO.RequestMethod.sms_name, DTO.RequestMethod.sms_key), mobile, text, null));
#endif
        }
        public string SendTokenSms(string mobile, string text) {
#if DEBUG
            return "0";
#else
            var sms = GetTokenSetting().sms;
            var log = IocHelper.Get<ILogHelper>("info");
            if (sms.is_open) {
                var data = new {
                    uid = sms.sms_name, pwd = sms.sms_key, mobile = mobile,
                    content = text
                };
                var result = sms.sms_url.PostJsonAsync(data).ReceiveJson<sms_result>().Result;
                if (result.status.Equals("success")) return "0";

                log.Info(result.respCode + "---" + result.status);
                return GetSmsError(int.Parse(result.respCode));
            } else {
                return "0";
            }

            //PostMsg postMsg = new PostMsg();
            //var smsip = DTO.RequestMethod.sms_url.Split(':');
            ////postMsg.SetGateWay("192.168.0.208", 8088, LinkType.SHORTLINK);// 设置上行网关地址、端口
            //postMsg.SetMOAddress(smsip[0], int.Parse(smsip[1]), LinkType.SHORTLINK);// 设置下行网关地址、端口   mos:mt：211.147.239.62 端口：9080
            //return GetSmsError(postMsg.Post(postMsg.SetUser(DTO.RequestMethod.sms_name, DTO.RequestMethod.sms_key), mobile, text, null));
#endif
        }
        /// <summary>
        /// 通用发送短信
        /// </summary>
        /// <param name="mobile"></param>
        /// <param name="text"></param>
        /// <param name="sms_setting"></param>
        /// <returns></returns>
        public string SendCommonSms(string mobile, string text,token_sms_setting sms_setting) {
#if DEBUG
            return "0";
#else
            var sms = sms_setting;
            var log = IocHelper.Get<ILogHelper>("info");
            if (sms.is_open) {
                var data = new {
                    uid = sms.sms_name, pwd = sms.sms_key, mobile = mobile,
                    content = text
                };
                var result = sms.sms_url.PostJsonAsync(data).ReceiveJson<sms_result>().Result;
                if (result.status.Equals("success")) return "0";

                log.Info(result.respCode + "---" + result.status);
                return GetSmsError(int.Parse(result.respCode));
            } else {
                return "0";
            }
#endif
        }
        private string GetSmsError(int result) {
            string error = "未知错误";
            switch (result) {
                case 0:
                    error = "0";
                    break;
                case -2:
                    error = "发送参数填定不正确";
                    break;
                case -3:
                    error = "用户载入延迟";
                    break;
                case -6:
                    error = "密码错误";
                    break;
                case -7:
                    error = "用户不存在";
                    break;
                case -11:
                    error = "发送号码数理大于最大发送数量";
                    break;
                case -12:
                    error = "余额不足";
                    break;
                case -99:
                    error = "内部处理错误";
                    break;
            }
            return error;
        }
       /// <summary>
       /// 台湾短信验证码格式
       /// </summary>
       /// <param name="status"></param>
       /// <returns></returns>
        private string GetTaiWanSmsError(string status) {
           string error = "未知错误";
            switch (status) {
                case "*": error = "系統發生錯誤，請聯絡三竹資訊窗口人員"; break;
                case "a": error = "簡訊發送功能暫時停止服務，請稍候再試"; break;
                case "b": error = "簡訊發送功能暫時停止服務，請稍候再試"; break;
                case "c": error = "請輸入帳號"; break;
                case "d": error = "請輸入密碼"; break;
                case "e": error = "帳號、密碼錯誤"; break;
                case "f": error = "帳號已過期"; break;
                case "h": error = "帳號已被停用"; break;
                case "k": error = "無效的連線位址"; break;
                case "m": error = "必須變更密碼，在變更密碼前，無法使用簡訊發送服務"; break;
                case "n": error = "密碼已逾期，在變更密碼前，將無法使用簡訊發送服務"; break;
                case "p": error = "沒有權限使用外部Http程式"; break;
                case "r": error = "系統暫停服務，請稍後再試"; break;
                case "s": error = "帳務處理失敗，無法發送簡訊"; break;
                case "t": error = "簡訊已過期"; break;
                case "u": error = "簡訊內容不得為空白"; break;
                case "v": error = "無效的手機號碼"; break;
                case "0": error = "預約傳送中"; break;
                case "1": error = "已送達業者"; break;
                case "2": error = "已送達業者"; break;
                case "3": error = "已送達業者"; break;
                case "4": error = "已送達手機"; break;
                case "5": error = "內容有錯誤"; break;
                case "6": error = "門號有錯誤"; break;
                case "7": error = "簡訊已停用"; break;
                case "8": error = "逾時無送達"; break;
                case "9": error = "預約已取消"; break;
                
            }
            return error;
        }
        /// <summary>
        /// 拓垦验证码发送内容
        /// </summary>
        /// <param name="type"></param>
        /// <param name="mobile_code"></param>
        /// <returns></returns>
        private string GetSmsContent(string type, string mobile_code) {
            string msg = string.Empty;
            switch (type) {
                case "token_login":
                case "token_login_code":
                    if (mobile_code == "886") { msg = "驗證碼：{0}，您正在登錄拓垦「驗證碼告知他人將會對您的賬户造成損失，請勿洩露」"; } else { msg = "验证码：{0}，您正在登录拓垦「验证码告知他人将会对您的账户造成损失，请勿泄露"; }
                    break;
                case "token_register": if (mobile_code == "886") { msg = "驗證碼：{0}，您正在註冊賬號「驗證碼告知他人將會對您的賬戶造成損失，請勿洩露"; } else { msg = "验证码：{0}，您正在注册账号「验证码告知他人将会对您的账户造成损失，请勿泄露"; } break;
                case "token_forget": if (mobile_code == "886") { msg = "驗證碼：{0}，您正在修改登錄密碼「驗證碼告知他人將會對您的賬戶造成損失，請勿洩露」"; } else { msg = "验证码：{0}，您正在修改登录密码「验证码告知他人将会对您的账户造成损失，请勿泄露"; } break;
                default: msg = "您的验证码 {0} 有效时间3分钟"; break;
            }
            return msg;
        }
        /// <summary>
        /// 台湾发送短信验证码
        /// </summary>
        /// <param name="mobile"></param>
        /// <param name="content"></param>
        /// <returns></returns>
        public int SendTaiWanSms(string mobile, string content) {
            string strbig5 = HttpUtility.UrlEncode(content, Encoding.GetEncoding(950));
            string url = string.Format("http://smexpress.mitake.com.tw:9600/SmSendGet.asp?username=58498506&password=0288&dstaddr={0}&DestName={1}&dlvtime={2}&vldtime={3}&smbody={4}&response={5}", mobile, "", "", "", content, "");
            var api_result = url.GetStringAsync().Result;
           var array= api_result.Split(new string[] { "\r\n","=" }, StringSplitOptions.None).ToArray();
            var log = IocHelper.Get<ILogHelper>("info");
            log.Info(string.Format("status:{0}---error:{1}", array[4], GetTaiWanSmsError(array[4])));
            if (array[4] == "1" || array[4] == "2" || array[4] == "3" || array[4] == "4") return 1;
            else return 0;
        
        }
    }

}
